﻿#include <windows.h>
#include"bitmap.h"
const char g_szClassName[] = "myWindowClass";
MBITMAP          bmpImage;
void LoadBitmap1(HDC hdc)
{
	string          sImageLocation      = "a.bmp";
	
	FILE*           fbmpImage           = NULL;
	long fileSize;
    char *rawData;
	unsigned int    ImagePixelAmount    = 0;
	bool            bImageLoaded        = false;

	do{

		//Open the image file
		fopen_s(&fbmpImage, sImageLocation.c_str(), "rb");

		//Check whether the image could be loaded successfully or not
		if(fbmpImage == NULL){
			//cout << "Loading the image file failed!" << " " << endl;
			return;
		}
		if(fbmpImage != NULL){
			//cout << "Loaded the image file successfully!" << endl;
			bImageLoaded = true;
		}
		//Read the BITMAP FILE HEADER
		fseek(fbmpImage, 0, SEEK_SET);
		fread(&bmpImage.FILEHEADER, sizeof(MBITMAPFILEHEADER), 1, fbmpImage);

		//Check if the image is a valid bitmap file
		if(bmpImage.FILEHEADER.bfType != 19778){
				bImageLoaded = false;
			//	cout << "Image is not a valid Bitmap file!" << endl;
				fclose(fbmpImage);
		}
	}while(bImageLoaded = false);

	//Read the BITMAP INFO HEADER
	fread(&bmpImage.INFOHEADER, sizeof(MBITMAPINFOHEADER), 1, fbmpImage);
	ImagePixelAmount = bmpImage.INFOHEADER.biHeight * bmpImage.INFOHEADER.biWidth;

	//Create space in memory and read in pixel data from the image
	bmpImage.IMAGEDATA = (rgbMPIXEL*)malloc(sizeof(rgbMPIXEL) * ImagePixelAmount);
	fseek(fbmpImage, bmpImage.FILEHEADER.bfOffBits, SEEK_SET);
	fread(bmpImage.IMAGEDATA, ImagePixelAmount * sizeof(rgbMPIXEL), 1, fbmpImage);

	fseek(fbmpImage, 0, SEEK_END);
    fileSize = ftell(fbmpImage);
    fseek(fbmpImage, 0, SEEK_SET);
	
	rawData = (char*)malloc( fileSize * sizeof(char) );
    fread(rawData, sizeof(char), fileSize, fbmpImage);

	fclose(fbmpImage);
	if(bmpImage.INFOHEADER.biBitCount==24)
	{
		COLORREF color;
		int z=bmpImage.INFOHEADER.biHeight;
		unsigned int r,g,b;

		for(int y =0; y <bmpImage.INFOHEADER.biHeight ; y++){

			for(int x = 0; x < bmpImage.INFOHEADER.biWidth; x++){
				r=(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].r;
				g=(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].g;
				b=(unsigned int) bmpImage.IMAGEDATA[y * bmpImage.INFOHEADER.biWidth + x].b;
				color=RGB(r,g,b);
				SetPixel(hdc,x,z,color);
			}
			z--;
		}
	}
	if(bmpImage.INFOHEADER.biBitCount==8)
	{
		COLORREF *colour_table_offset;
		colour_table_offset = (COLORREF*) (rawData + (sizeof(MBITMAPFILEHEADER) + sizeof(MBITMAPINFOHEADER)));

		int bytesPerRow = bmpImage.INFOHEADER.biWidth + (bmpImage.INFOHEADER.biWidth%2);    // rows must be a multiple of 2 bytes

		int y, x;
		int z=bmpImage.INFOHEADER.biHeight;
		for (y=0; y<bmpImage.INFOHEADER.biHeight; y++)
		{
			UINT8 *curRow;
			curRow = (UINT8*) (bmpImage.FILEHEADER.bfOffBits + (y*bytesPerRow) + rawData);
			for (x=0; x<bmpImage.INFOHEADER.biWidth; x++)
			{
				UINT32 palIndex;
				palIndex = curRow[x];
				COLORREF curCol = colour_table_offset[palIndex];

				UINT8 r, g, b;
				b = (curCol>>0) & 0xFF;
				g = (curCol>>8) & 0xFF;
				r = (curCol>>16) & 0xFF;
				SetPixel(hdc, x, z, RGB(r,g,b) );
			}
			z--;
		}
		
	}
	free(rawData);
}


void dispBmp(char *filename, HDC hdc)
{
    FILE *fp;
    long fileSize;
    char *rawData;

    fp = fopen(filename, "rb");
    fseek(fp, 0, SEEK_END);
    fileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);
	
	
    rawData = (char*)malloc( fileSize * sizeof(char) );
    fread(rawData, sizeof(char), fileSize, fp);

	MBITMAP *bmHdr;
	bmHdr = (MBITMAP*)rawData;

	COLORREF *colour_table_offset;
	colour_table_offset = (COLORREF*) (rawData + (sizeof(MBITMAPFILEHEADER) + sizeof(MBITMAPINFOHEADER)));

	int bytesPerRow = bmHdr->INFOHEADER.biWidth + (bmHdr->INFOHEADER.biWidth%2);    // rows must be a multiple of 2 bytes

    int y, x;
	int z=bmHdr->INFOHEADER.biHeight;
    for (y=0; y<bmHdr->INFOHEADER.biHeight; y++)
    {
		UINT8 *curRow;
		curRow = (UINT8*) (bmHdr->FILEHEADER.bfOffBits + (y*bytesPerRow) + rawData);
		for (x=0; x<bmHdr->INFOHEADER.biWidth; x++)
        {
			UINT32 palIndex;
            palIndex = curRow[x];
			COLORREF curCol = colour_table_offset[palIndex];
          //  SetPixel(hdc, x, y, curCol);

			UINT8 r, g, b;
            b = (curCol>>0) & 0xFF;
            g = (curCol>>8) & 0xFF;
            r = (curCol>>16) & 0xFF;
            SetPixel(hdc, x, z, RGB(r,g,b) );
        }
		z--;
    }
    free(rawData);
    fclose(fp);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		 case WM_PAINT:
		{
			RECT rcClient;
				PAINTSTRUCT ps;
				HDC hdc=BeginPaint(hwnd,&ps);
				GetClientRect(hwnd, &rcClient);	
				LoadBitmap1(hdc);
				//dispBmp("256.bmp",hdc);
			EndPaint(hwnd,&ps);
		}
		break;
		case WM_CLOSE:
			DestroyWindow(hwnd);
		break;
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		default:
			return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;

	//Step 1: Registering the Window Class
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = WndProc;
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	// Step 2: Creating the Window
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		g_szClassName,
		"Load Bitmap",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, 700, 500,
		NULL, NULL, hInstance, NULL);

	if(hwnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	// Step 3: The Message Loop
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}
